#include <Eigen/Dense>
#include <pybind11/embed.h> // everything needed for embedding
#include <iostream>

#include<pybind11/eigen.h>

namespace py = pybind11;


#include <opencv2/opencv.hpp>

using cv::Mat;

typedef Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> MatrixU8;
typedef Eigen::Matrix<unsigned int, Eigen::Dynamic, Eigen::Dynamic> MatrixInt;

#include <stdio.h>
#include <sys/timeb.h>

void draw_box_from_matrix_ret(MatrixInt matrix, cv::Mat img, bool show = false, int elapse_time=40) {
    int r = matrix.rows();

    for (int i = 0; i < r; ++i) {
        int xmin = matrix(i, 0);
        int ymin = matrix(i, 1);
        int xmax = matrix(i, 2);
        int ymax = matrix(i, 3);
        cv::rectangle(img, cvPoint(xmin, ymin), cvPoint(xmax, ymax), cv::Scalar(0, 0, 255), 1, 1, 0);
    }
    if (show) {
        cv::namedWindow("image", 0);
        cv::resizeWindow("image", 960, 540);
        imshow("image", img);
        cvWaitKey(elapse_time);
    }

}

int main() {
//    const char* imagename = "test_im.jpg";
    const char *imagename = "test_im1080.jpg";

    //从文件中读入图像
    cv::Mat img = cv::imread(imagename, 1);
    int height = img.rows;
    int width = img.cols;
    printf("w:%d,h:%d\n", width, height);


    if (img.empty()) {
        fprintf(stderr, "Can not load image %s\n", imagename);
        return -1;
    }
//    cv::imshow("image", img);
//    cv::waitKey(500);
    try {
        //        Py_SetProgramName("PYTHON");
        py::scoped_interpreter guard{};

        py::module py_test = py::module::import("py_test");

        MatrixU8 m_b(height, width);
        MatrixU8 m_g(height, width);
        MatrixU8 m_r(height, width);

        struct timeb t1;
        ftime(&t1);
        std::cout << "time:" << t1.time << "." << t1.millitm << std::endl;

        int shape[3] = {height,width,3};
        py::array_t<unsigned char> k(shape,img.data) ;

        ftime(&t1);
        std::cout << "time:" << t1.time << "." << t1.millitm << std::endl;

        py::object result = py_test.attr("infer")(k);
//        MatrixInt res = result.cast<MatrixInt>();
        // matrix is [[xmin, ymin,xmax,ymax,id] ... ]
//        std::cout << "In c++ \n" << res << std::endl;
//        draw_box_from_matrix_ret(res, img, true, 1000);
    }
    catch (std::exception ex) {
        std::cout << "ERROR   : " << ex.what() << std::endl;
    }
    return 1;
}
